package com.gallsoft.games.bennyadv;

import javax.microedition.khronos.opengles.GL10;

import com.gallsoft.games.bennyadv.Enemy.EnemyType;
import com.gallsoft.games.framework.gamedev2d.Animation;
import com.gallsoft.games.framework.gamedev2d.SpriteBatcher;
import com.gallsoft.games.framework.gl.Camera2D;
import com.gallsoft.games.framework.gl.Texture;
import com.gallsoft.games.framework.gl.TextureRegion;
import com.gallsoft.games.framework.impl.GLGraphics;
import com.gallsoft.games.framework.math.Vector2;

public class WorldRenderer {

    //static final float FRUSTUM_WIDTH = 10;
    //static final float FRUSTUM_HEIGHT = 15;
    static final float FRUSTUM_WIDTH = 15;
    static final float FRUSTUM_HEIGHT = 10;
    GLGraphics glGraphics;
    World world;
    Camera2D cam;
    SpriteBatcher batcher;
    private float lastSide = 1;
    float angle = 0;

    public WorldRenderer(GLGraphics glGraphics, SpriteBatcher batcher, World world) {
        this.glGraphics = glGraphics;
        this.world = world;
        this.cam = new Camera2D(glGraphics, FRUSTUM_WIDTH, FRUSTUM_HEIGHT);
        this.batcher = batcher;
        
        if (world.bob.position.x < 15)            
            cam.position.x = 7.5f;
        else
            cam.position.x = 22.5f;
        
        if (world.bob.position.y < 10)
            cam.position.y = 5.0f;
        else
            cam.position.y = 15.0f;
        
        cam.setMaxPosition(new Vector2(22.0f, 30.0f));
    }

    public void render() {
        //if (world.bob.position.y > cam.position.y)
        //    cam.position.y = world.bob.position.y;
        
        if (world.bob.position.x > cam.position.x && (cam.position.x < cam.getMaxXPosition()))
            cam.position.x = world.bob.position.x;
        else if (world.bob.position.x < cam.position.x  && (cam.position.x > FRUSTUM_WIDTH / 2))
            cam.position.x = world.bob.position.x;
        else if (cam.position.x < FRUSTUM_WIDTH / 2)
            cam.position.x = FRUSTUM_WIDTH / 2;
        
        if (world.bob.position.y > cam.position.y && (cam.position.y < cam.getMaxYPosition()))
            cam.position.y = world.bob.position.y;
        else if (world.bob.position.y < cam.position.y  && (cam.position.y > FRUSTUM_HEIGHT / 2))
            cam.position.y = world.bob.position.y;
        else if (cam.position.y < FRUSTUM_HEIGHT / 2)
            cam.position.y = FRUSTUM_HEIGHT / 2;
        
        cam.setViewportAndMatrices();
        renderBackground();
        renderObjects();
    }

    public void renderBackground() {
        Texture background = world.background.texture;
        TextureRegion backgroundRegion = world.background;
        
        batcher.beginBatch(background);
        //batcher.drawSprite(cam.position.x, cam.position.y, FRUSTUM_WIDTH, FRUSTUM_HEIGHT, backgroundRegion);
        batcher.drawSprite(FRUSTUM_WIDTH, FRUSTUM_HEIGHT, FRUSTUM_WIDTH * 2.0f, FRUSTUM_HEIGHT * 1.6f * 2.0f, backgroundRegion);
        batcher.endBatch();
    }

    public void renderObjects() {
        GL10 gl = glGraphics.getGL();
        gl.glEnable(GL10.GL_BLEND);
        gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);

        batcher.beginBatch(Assets.items);
        
        renderScenery();
        //renderSwitches();
        renderBlocks();
        renderPlatforms();
        renderLadders();
        renderItems();        
        renderExit();
        
        renderEnemies();
        renderBob();
        
        renderScore();
        renderControls();

        batcher.endBatch();
        
        gl.glDisable(GL10.GL_BLEND);
    }

    
    private void renderBob() {
        TextureRegion keyFrame;
        float side = 1;

        switch (world.bob.state) {
            case Bob.BOB_STATE_WALK:
                keyFrame = Assets.bennyWalk.getKeyFrame(world.bob.stateTime, Animation.ANIMATION_LOOPING);
                break;
            
            case Bob.BOB_STATE_JUMP:
                keyFrame = Assets.bennyWalk.getKeyFrame(world.bob.stateTime, Animation.ANIMATION_LOOPING);
                break;
                
            case Bob.BOB_STATE_FALL:
                keyFrame = Assets.bennyWalk.getKeyFrame(world.bob.stateTime, Animation.ANIMATION_LOOPING);
                break;
                
            case Bob.BOB_STATE_HIT:
                keyFrame = Assets.bennyDie.getKeyFrame(world.bob.stateTime, Animation.ANIMATION_LOOPING);
                break;
                
            case Bob.BOB_STATE_CLIMB:
                keyFrame = Assets.bennyClimb.getKeyFrame(world.bob.stateTime, Animation.ANIMATION_LOOPING);
                break;
                
            default:
                keyFrame = Assets.bennyWalk.getKeyFrame(0, Animation.ANIMATION_LOOPING);
                break;
        }

        // Draw benny facing left or right depending on velocity
        //if (world.bob.velocity.x == 0 || world.bob.state == Bob.BOB_STATE_STOP)
        //if (world.bob.state == Bob.BOB_STATE_STOP || world.bob.state == Bob.BOB_STATE_FALL)
        //    side = lastSide;
        //else {
        //    side = world.bob.velocity.x < 0 ? -1 : 1;
        //}       
        
        //lastSide = side;
        batcher.drawSprite(world.bob.position.x, world.bob.position.y, world.bob.facing * 2, 2, keyFrame);
        //batcher.drawSprite(world.bob.bounds.lowerLeft.x + world.bob.bounds.width / 2, world.bob.bounds.lowerLeft.y + world.bob.bounds.height / 2, world.bob.bounds.width, world.bob.bounds.height, Assets.debug_box_blue_region);
    }

    private void renderEnemies() {
        TextureRegion keyFrame;
        int len = world.enemies.size();
        float side = 1;
        
        for(int i = 0; i < len; i++) {
            Enemy enemy = world.enemies.get(i);
            
            switch (enemy.enemyType) {
            case FLY:
                keyFrame = Assets.fly.getKeyFrame(enemy.stateTime, Animation.ANIMATION_LOOPING);
                break;
                
            case SNAIL:
                keyFrame = Assets.snail.getKeyFrame(enemy.stateTime, Animation.ANIMATION_LOOPING);
                break;
                
            case CRAB:
                keyFrame = Assets.crab.getKeyFrame(enemy.stateTime, Animation.ANIMATION_LOOPING);
                break;
                
            case EGG:
                keyFrame = Assets.egg.getKeyFrame(enemy.stateTime, Animation.ANIMATION_LOOPING);
                break;
                
            case PINKSWEET:
                keyFrame = Assets.pinkSweet.getKeyFrame(enemy.stateTime, Animation.ANIMATION_LOOPING);
                break;
                
            case BLUESWEET:
                keyFrame = Assets.blueSweet.getKeyFrame(enemy.stateTime, Animation.ANIMATION_LOOPING);
                break;
                
            case TOMATO:
                keyFrame = Assets.tomato.getKeyFrame(enemy.stateTime, Animation.ANIMATION_LOOPING);
                break;
                
                default:
                    keyFrame = Assets.strawberry;
            }
            
            //TextureRegion keyFrame = Assets.enemy.getKeyFrame(fly.stateTime, Animation.ANIMATION_LOOPING);
            side = enemy.velocity.x < 0 ? -1 : 1;
            batcher.drawSprite(enemy.position.x, enemy.position.y, side * 2, 2, keyFrame);
        }
    }
    
    private void renderPlatforms() {
        int len = world.platforms.size();
        for (int i = 0; i < len; i++) {
            Platform platform = world.platforms.get(i);
            
            float flip = platform.flip ? -1 : 1;
            batcher.drawSprite(platform.position.x, platform.position.y, flip * platform.width, platform.height, platform.angle, platform.platformGraphic);
            //batcher.drawSprite(platform.bounds.lowerLeft.x + platform.bounds.width / 2, platform.bounds.lowerLeft.y + platform.bounds.height / 2, platform.bounds.width, platform.bounds.height, Assets.debug_box_red_region);
        }
        
        len = world.movingPlatforms.size();
        for (int i = 0; i < len; i++) {
            Platform platform = world.movingPlatforms.get(i);
            
            float flip = platform.flip ? -1 : 1;
            batcher.drawSprite(platform.position.x, platform.position.y, flip * platform.width, platform.height, platform.platformGraphic);
            //batcher.drawSprite(platform.bounds.lowerLeft.x + platform.bounds.width / 2, platform.bounds.lowerLeft.y + platform.bounds.height / 2, platform.bounds.width, platform.bounds.height, Assets.debug_box_red_region);
        }
    }

    private void renderBlocks() {
        int len = world.solidBlocks.size();
        for (int i = 0; i < len; i++) {
            SolidBlock solidBlock = world.solidBlocks.get(i);
            batcher.drawSprite(solidBlock.position.x, solidBlock.position.y, 1, 1, solidBlock.blockGraphic);
        }
    }
    
    private void renderLadders() {
        int len = world.ladderBlocks.size();
        for (int i = 0; i < len; i++) {
            LadderBlock ladderBlock = world.ladderBlocks.get(i);
            batcher.drawSprite(ladderBlock.position.x, ladderBlock.position.y, 1, 1, ladderBlock.blockGraphic);
        }
    }
    
    private void renderItems() {
        angle += 2;
        if (angle >= 360) angle = 0;
        
        int len = world.items.size();

        for (int i = 0; i < len; i++) {
            Item coin = world.items.get(i);
            // TextureRegion keyFrame = Assets.foodAnim.getKeyFrame(food.stateTime, Animation.ANIMATION_LOOPING);
            // batcher.drawSprite(food.position.x, food.position.y, 1, 1, keyFrame);
            batcher.drawSprite(coin.position.x, coin.position.y, 1, 1, angle, coin.getTexture());
        }
    }

    private void renderScenery() {
        int len = world.scenery.size();

        for (int i = 0; i < len; i++) {
            Scenery scenery = world.scenery.get(i);
            batcher.drawSprite(scenery.position.x, scenery.position.y, 1, 1, scenery.sceneryGraphic);
        }        
        
        // Render switches
        len = world.switches.size();

        for (int i = 0; i < len; i++) {
            Scenery scenery = world.switches.get(i);
            float flip = scenery.state ? -1 : 1;
            batcher.drawSprite(scenery.position.x, scenery.position.y, 1, flip, scenery.angle, scenery.sceneryGraphic);
        }  
        
        // Render keys
        len = world.keys.size();

        for (int i = 0; i < len; i++) {
            Scenery key = world.keys.get(i);
            
            if (!key.state) {
                float flip = key.state ? -1 : 1;
                batcher.drawSprite(key.position.x, key.position.y, 1, flip, angle, key.sceneryGraphic);
            }
        }  
        
        // Render doors
        len = world.doors.size();

        for (int i = 0; i < len; i++) {
            Scenery scenery = world.doors.get(i);
            float flip = scenery.state ? -2 : 2;
            batcher.drawSprite(scenery.position.x, scenery.position.y, 2, flip, scenery.sceneryGraphic);
        }  
        
        // Render spikes
        len = world.spikes.size();

        for (int i = 0; i < len; i++) {
            Scenery spike = world.spikes.get(i);
            //float flip = scenery.state ? -1 : 1;
            batcher.drawSprite(spike.position.x, spike.position.y, 1, 1, spike.sceneryGraphic);
        }        
    }
        
    private void renderExit() {
        TextureRegion exitImage;
        Exit exit = world.exit;
        
        switch (exit.type) {
        case WOODEN_EXIT:
            exitImage = Assets.wood_exit;
            break;
            
        case KENNEL:
            exitImage = Assets.kennel;
            break;
            
        default:
            exitImage = Assets.wood_exit;
            break;
        }

        batcher.drawSprite(exit.position.x, exit.position.y, 2, 2, exitImage);        
    }
    
    private void renderControls() {
        //batcher.drawSprite(cam.position.x - 6, cam.position.y + 3, 2, 2, Assets.button);
        batcher.drawSprite(cam.position.x + 6, cam.position.y - 3, 2, 2, Assets.arrow);
        batcher.drawSprite(cam.position.x + 3, cam.position.y - 3, -2, 2, Assets.arrow);
        batcher.drawSprite(cam.position.x + 4.5f, cam.position.y - 1.5f, 2, -2, Assets.arrowup);
    }
    
    private void renderScore() {
        //batcher.drawSprite(cam.position.x - 5.0f, cam.position.y + 4.6f, 3, 1, Assets.scoreString);        
        //batcher.drawSprite(cam.position.x, cam.position.y + 4.6f, 2, 1, Assets.timeString);        
        //batcher.drawSprite(cam.position.x + 4.5f, cam.position.y + 4.6f, 3, 1, Assets.levelString);        
    }
}
